#region imported Namespaces
using System;
using System.Data;
using System.Text;
using System.Data.SqlClient;
using BO = PHSRAG.Insight21.BusinessObjects;
using PHSRAG.Insight21.SearchContext;
using Utils = PHSRAG.Insight21.InsightUtilities;
using Utility = PHSRAG.Utility;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
#endregion

namespace PHSRAG.Insight21.Purchasing
{
	/// <summary>
	/// Business class for reconcile unmatched orders. 
	/// It supports loading of unmatched user order which the user has access to.
	/// It also has methods to support Sorting and filtering of user orders.
	/// </summary>
	public class ReconcileUnMatchedOrders: BO.BusinessObject
	{
		#region Constants (Private)
		private const string	ReconcileUnMatchedKey		= "ReconcileUnMatched_669B9CD7-3F35-4017-950C-289BAA9EDF26";
		private const string	ReconcileUnMatchedSPName	= "GetReconcileUnmatched";

		/// <summary>
		/// The reconcile bit ensures that the returned datatable has an option "All" alongwiththe list of user order type
		/// </summary>
		private const int		ReconcileBit				= 1;
		#endregion

		#region Enumerations (Private)

		/// <summary>
		/// Enumerates the data tables returned by SP GetReconcileUnmatched.
		/// </summary>
		private enum DataTableIndex
		{
			Insight,
			PeopleSoft,
			Count
		}

		#endregion
	
		#region Instance Variables (Private)
		private bool			insightSortAscending		= true;
		private bool			peopleSoftSortAscending		= true;
		// Keep this in sync with what the stored proc orders by.
		private string			insightSortColumn			= string.Empty;
		// Keep this in sync with what the stored proc orders by.
		private string			peopleSoftSortColumn		= string.Empty;		
		#endregion

		#region Public Properties
		/// <summary>
		/// Get the key to be used in all caching operations for this instance of the object.
		/// </summary>
		public static string CacheKey	{ get { return ReconcileUnMatchedKey; } }
		/// <summary>
		/// Get the sort sequence for insight orders.
		/// </summary>
		public bool InsightSortAscending
		{
			get { return insightSortAscending; }
		}

		/// <summary>
		/// Get the name of the sort column for insight orders.
		/// </summary>
		public string InsightSortColumn
		{
			get { return insightSortColumn; }
		}
		
		/// <summary>
		/// Get the sort sequence for peoplesoft orders.
		/// </summary>
		public bool PeopleSoftSortAscending
		{
			get { return peopleSoftSortAscending; }
		}

		/// <summary>
		/// Get the name of the sort column for peoplesoft orders.
		/// </summary>
		public string PeopleSoftSortColumn
		{
			get { return peopleSoftSortColumn; }
		}

		#endregion
		
		#region Constructor
		/// <summary>
		/// Initializes the base class with the specified cache policy.
		/// </summary>
		/// <param name="cachePolicy">prevalent cache policy</param>		
		public ReconcileUnMatchedOrders(ICachePolicy cachePolicy) : base(cachePolicy){}
		#endregion

		#region Public Methods
		/// <summary>
		/// Sorts the DataTable containing user orders.
		/// </summary>
		/// <param name="tableName">the name of the DataTable to sort.</param>
		/// <returns>DataView having sorted data</returns>
		public DataView Sort(string dataTableName)
		{
			DataView dataView = null;

			// Check which table to set as source of dataView
			if(dataTableName == Constants.ReconcileUnMatchedInsightTableName)
			{
				dataView = new DataView(DataContainer.Tables[Constants.ReconcileUnMatchedInsightTableName]);				
				
				if(!insightSortColumn.Equals(string.Empty))
					dataView.Sort = string.Format("{0} {1}", insightSortColumn,
						insightSortAscending ? Constants.SortOrderAscending : Constants.SortOrderDescending);
			}
			else
			{
				dataView = new DataView(DataContainer.Tables[Constants.ReconcileUnMatchedPSTableName]);
				if(!peopleSoftSortColumn.Equals(string.Empty))
					dataView.Sort = string.Format("{0} {1}", peopleSoftSortColumn,
						peopleSoftSortAscending ? Constants.SortOrderAscending : Constants.SortOrderDescending);
			}
			return dataView;
		}
		
		/// <summary>
		/// This method sets the sort order and sort column for Insight
		/// or peoplesoft records. It uses the parameter sourceTable to determine
		/// the table to which the passed sort criteria is applicable.
		/// </summary>
		/// <param name="columnName">Column to sort by</param>
		/// <param name="sourceTable">Data table to which passed sort criteria is applicable</param>
		public void ProcessSortCriteria(string columnName, string sourceTable)
		{
			// Check for the source table
			if(sourceTable == Constants.ReconcileUnMatchedInsightTableName)
			{
				insightSortAscending = (insightSortColumn == columnName) ? 
					!insightSortAscending : insightSortAscending;
				insightSortColumn = columnName;
			}
			else
			{
				peopleSoftSortAscending = (peopleSoftSortColumn == columnName) ? 
					!peopleSoftSortAscending : peopleSoftSortAscending;
				peopleSoftSortColumn = columnName;
			}			
		}

		#endregion		

		#region Business Object Methods
		/// <summary>
		/// Initializes and loads the datacontainer with reconcile matched user orders.
		/// The method expects SearchCriteria object in the params object array.
		/// </summary>
		/// <param name="connectionString">connection string pointing to the database to get data from.</param>
		/// <param name="args">arguments to load the matched user order records.</param>
		public override void Load(string connectionString, params object[] args)
		{
			if (args[0] == null)
				throw new Exception("Reconcile Unmatched load requires search criteria containing at least a domain user ID.");
			
			SearchCriteria searchCriteria = (SearchCriteria)args[0];
			
			try
			{
				string daysTransactionsWithin = searchCriteria[Utils.Constants.PurchasingSearchKey.DaysTransactionsWithinKey];

				DataContainer = Utility.DataAccess.GetDataSet(connectionString, ReconcileUnMatchedSPName,
					Utility.DataAccess.BuildSqlParameterArray(
					"@domainUserID", SqlDbType.Int, searchCriteria[Utils.Constants.DomainUserIDKey],
					"@orderTypeID", SqlDbType.Int, searchCriteria[Utils.Constants.PurchasingSearchKey.UserOrderTypeViewKey],
					"@transactionStartDate", SqlDbType.DateTime,
					daysTransactionsWithin == null ? searchCriteria[Utils.Constants.PurchasingSearchKey.TransactionDateFromKey] : DateTime.Now.Date.AddDays(-Convert.ToDouble(daysTransactionsWithin)).ToShortDateString(),
					"@transactionEndDate", SqlDbType.DateTime,
					daysTransactionsWithin == null ? searchCriteria[Utils.Constants.PurchasingSearchKey.TransactionDateToKey] : DateTime.Now.ToShortDateString(),
					"@orderNumber", SqlDbType.VarChar, searchCriteria[Utils.Constants.PurchasingSearchKey.PONumberKey],
					"@piID", SqlDbType.Int, searchCriteria[Utils.Constants.PIIDKey],
					"@chiefCodeList", SqlDbType.VarChar, searchCriteria.COSIds,
					"@fundNumber", SqlDbType.VarChar, searchCriteria[Utils.Constants.FundIDKey],
					"@amount", SqlDbType.Money, searchCriteria[Utils.Constants.PurchasingSearchKey.TotalOrderAmountKey],
					"@requestorName", SqlDbType.VarChar, searchCriteria[Utils.Constants.PurchasingSearchKey.RequestorNameKey],
					"@vendorName", SqlDbType.VarChar, searchCriteria[Utils.Constants.PurchasingSearchKey.VendorNameKey],
					"@invoiceNumber", SqlDbType.VarChar, searchCriteria[Utils.Constants.PurchasingSearchKey.InvoiceNumberKey],
					"@invoiceDate", SqlDbType.DateTime, searchCriteria[Utils.Constants.PurchasingSearchKey.InvoiceDateKey]));					

				if(!DataContainer.Tables.Count.Equals((int)DataTableIndex.Count))
					throw new Exception(string.Format("Failed to load data for matched orders. Expected {0} tables but {1} tables were returned.",
						(int)DataTableIndex.Count, DataContainer.Tables.Count));
				else
				{
					DataContainer.Tables[(int)DataTableIndex.Insight].TableName = 
						Constants.ReconcileUnMatchedInsightTableName;
					DataContainer.Tables[(int)DataTableIndex.PeopleSoft].TableName = 
						Constants.ReconcileUnMatchedPSTableName;
				}
			}
			catch(Exception ex)
			{
				throw(new Exception("Error in loading Reconcile Unmatched Orders", ex));
			}
		}

		/// <summary>
		/// Caches the ReconcileUnMatchedOrders object to cache using the prevalent cache policy
		/// </summary>
		public override void Cache()
		{
			CachePolicy.Cache(CacheKey,this);
		}
		
		/// <summary>
		/// Remove the current instance from the cache using the prevalent cache policy.
		/// </summary>
		public override void UnCache()
		{
			CachePolicy.UnCache(CacheKey);
		}

		#endregion	
	}
}
